package com.butte.mound.frame.record;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.json.JSONUtil;
import com.butte.mound.frame.token.BaseToken;
import com.butte.mound.frame.token.TokenContext;
import java.lang.reflect.Method;
import java.util.Objects;
import javax.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

@Slf4j
@Component
@Aspect
@RequiredArgsConstructor
public class LogAop {

    @Pointcut("@annotation(com.butte.mound.frame.record.LogRecord)")
    public void logPointCut() {
    }

    @Around("logPointCut()")
    public Object around (ProceedingJoinPoint point) throws Throwable {
        try{
            // 执行方法
            Object result = point.proceed();
            // 保存成功日志
            logRecord(point, LogStatusEnum.SUS.getId(),result);
            return result;
        } catch (Exception e){
            // 保存异常日志
            logRecord(point, LogStatusEnum.FAIL.getId(),e.getMessage());
            e.printStackTrace();
            throw e ;
        }
    }

    private void logRecord (ProceedingJoinPoint point,Integer status,Object result){
        try{
            // 请求
            HttpServletRequest request = ((ServletRequestAttributes) Objects
                    .requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();

            // 日志注解
            MethodSignature signature = (MethodSignature) point.getSignature();
            Method method = signature.getMethod();
            String className = point.getTarget().getClass().getName();
            Object[] reqParam = point.getArgs();
            LogRecord logRecord = method.getAnnotation(LogRecord.class);

            // 日志记录模型
            RecordModel recordModel = new RecordModel();
            recordModel.setStatus(status);
            LogTypeEnum logTypeEnum = logRecord.logType();

            // 用户信息
            BaseToken token = TokenContext.getToken();
            recordModel.setUserId(token.getUserId());
            recordModel.setAppName(token.getAppName());
            recordModel.setUserName(token.getUserName());

            // 注解信息
            recordModel.setLogType(logTypeEnum.getId());
            recordModel.setOpsClass(className);
            recordModel.setOpsMethod(method.getName());

            // 请求信息
            recordModel.setReqType(request.getMethod());
            recordModel.setReqUri(request.getRequestURI());
            recordModel.setReqParam(reqParam);
            recordModel.setRepParam(result);

            log.info(JSONUtil.toJsonStr(recordModel));
        } catch (Exception e){
            // 静默异常
        }
    }
}
